package com.wusuowei.auth.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wusuowei.auth.model.dto.UserExt;
import com.wusuowei.auth.model.vo.AuthParamsVo;
import com.wusuowei.auth.service.AuthService;
import com.wusuowei.ucenter.mapper.SysMenuMapper;
import com.wusuowei.ucenter.mapper.SysRoleMapper;
import com.wusuowei.ucenter.model.po.SysRole;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;


/**
 * @description 认证中心入口
 * @author LGY
 * @date 2023/04/11 18:59
 * @version 1.0.0
 */
@Slf4j
@Service
public class SecurityUserServiceImpl implements UserDetailsService {

    @Autowired
    SysMenuMapper sysMenuMapper;

    @Autowired
    SysRoleMapper sysRoleMapper;

    @Autowired
    ApplicationContext applicationContext;
    @Autowired
    PasswordEncoder passwordEncoder;

    /**
     * @description 封装前端传来的参数，根据不同类型调用不同的认证方式进行认证
     * @param s s
     * @return {@link UserDetails }
     * @author LGY
     * @date 2023/03/31 17:22
     */
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        AuthParamsVo paramsVo = null;
        try {
            paramsVo = JSON.parseObject(s, AuthParamsVo.class);
        } catch (Exception e) {
            throw new RuntimeException("认证请求数据格式不对");
        }
        //认证方式,
        String authType = paramsVo.getAuthType();
        //从spring容器中拿具体的认证bean实例
        AuthService authService = applicationContext.getBean(authType + "_authservice", AuthService.class);
        //开始认证,认证成功拿到用户信息
        UserExt userExt = authService.execute(paramsVo);
        userExt.setPassword(paramsVo.getPassword());
        BeanUtils.copyProperties(userExt, paramsVo);
        paramsVo.setRole(userExt.getRolesExt());
        return getUserPrincipal(paramsVo);
    }

    public UserDetails getUserPrincipal(AuthParamsVo user) {

        String password = passwordEncoder.encode(user.getPassword());
        user.setPassword(password);
        //user.setPassword(null);
        String userString = JSON.toJSONString(user);

        //这里会将
        UserDetails userDetails = User.withUsername(userString).password(password).authorities(getUserAuthority(user.getId())).build();
        return userDetails;
    }

    public List<GrantedAuthority> getUserAuthority(String userId) {
        //  格式ROLE_admin,ROLE_common,system:user:resetPwd,system:role:delete,system:user:list,system:menu:query,system:menu:list,system:menu:add,system:user:delete,system:role:list,system:role:menu,system:user:edit,system:user:query,system:role:edit,system:user:add,system:user:role,system:menu:delete,system:role:add,system:role:query,system:menu:edit
        String authority = this.getUserAuthorityInfo(userId);
        return AuthorityUtils.commaSeparatedStringToAuthorityList(authority);
    }

    public String getUserAuthorityInfo(String userId) {
        StringBuffer authority = new StringBuffer();
        // 根据用户id获取所有的角色信息
        List<SysRole> roleList = sysRoleMapper.selectList(new QueryWrapper<SysRole>().inSql("id", "SELECT role_id FROM sys_user_role WHERE user_id=" + userId));
        if (roleList.size() > 0) {
            String roleCodeStrs = roleList.stream().map(r -> "ROLE_" + r.getRoleKey()).collect(Collectors.joining(","));
            authority.append(roleCodeStrs);
        }
        List<String> permission = sysMenuMapper.getPermission(userId);
        if (permission.size() > 0) {
            authority.append(",");
            String menuCodeStrs = permission.stream().collect(Collectors.joining(","));
            authority.append(menuCodeStrs);
        }
        return authority.toString();
    }
}
